﻿using System;

namespace Red.Toolkit.PhysicalDecorationEditor
{
    public enum EPhysicsBaseType
    {
        EPBT_Base,
        EPBT_Actor,
        EPBT_Shape,
        EPBT_Max
    };

    public enum EPhysicsSimulation
    {
        EPS_Static,
        EPS_Dynamic,
        EPS_Kinematic,
        EPS_Undefined,
        EPS_Max
    };

    public enum EPhysicsShapeGeometryType
    {
        EPST_Box,
        EPST_Sphere,
        EPST_Capsule,
        EPST_Convex,
        EPST_Invalid,
        EPST_Max
    };

    public static class EnumExtensions
    {
        #region EPhysicsBaseType
        public static string ToFriendlyString(this EPhysicsBaseType me)
        {
            return ((UInt32)me).ToString(); 
            //return ("physics::" + me.ToString());         
        }

        public static bool FromString(out EPhysicsBaseType me, String str)
        {
            switch (str)
            {
                case "physics::EPBT_Base":
                    me = EPhysicsBaseType.EPBT_Base;
                    return true;
                case "physics::EPBT_Actor":
                    me = EPhysicsBaseType.EPBT_Actor;
                    return true;
                case "physics::EPBT_Shape":
                    me = EPhysicsBaseType.EPBT_Shape;
                    return true;
                case "physics::EPBT_Max":
                    me = EPhysicsBaseType.EPBT_Max;
                    return true;
                default:
                    me = EPhysicsBaseType.EPBT_Base;
                    return false;
            }
        }

        #endregion

        #region EPhysicsSimulation
        public static string ToFriendlyString(this EPhysicsSimulation me)
        {
            return ((UInt32)me).ToString();
            //return "physics::" + me.ToString();
        }

        public static bool FromString(out EPhysicsSimulation me, String str)
        {
            switch (str)
            {
                case "physics::EPS_Static":
                    me = EPhysicsSimulation.EPS_Static;
                    return true;
                case "physics::EPS_Dynamic":
                    me = EPhysicsSimulation.EPS_Dynamic;
                    return true;
                case "physics::EPS_Kinematic":
                    me = EPhysicsSimulation.EPS_Kinematic;
                    return true;
                case "physics::EPS_Undefined":
                    me = EPhysicsSimulation.EPS_Undefined;
                    return true;
                case "physics::EPS_Max":
                    me = EPhysicsSimulation.EPS_Max;
                    return true;
                default:
                    me = EPhysicsSimulation.EPS_Undefined;
                    return false;
            }
        }

        #endregion

        #region EPhysicsShapeGeometryType
        public static string ToFriendlyString(this EPhysicsShapeGeometryType me)
        {
            return ((UInt32)me).ToString();
            //return "physics::" + me.ToString();
        }
        public static bool FromString(out EPhysicsShapeGeometryType me, String str)
        {
            switch ( str )
            {
                case "physics::EPST_Box":
                    me = EPhysicsShapeGeometryType.EPST_Box;
                    return true;
                case "physics::EPST_Sphere":
                    me = EPhysicsShapeGeometryType.EPST_Sphere;
                    return true;
                case "physics::EPST_Capsule":
                    me = EPhysicsShapeGeometryType.EPST_Capsule;
                    return true;
                case "physics::EPST_Convex":
                    me = EPhysicsShapeGeometryType.EPST_Convex;
                    return true;
                case "physics::EPST_Invalid":
                    me = EPhysicsShapeGeometryType.EPST_Invalid;
                    return true;
                case "physics::EPST_Max":
                    me = EPhysicsShapeGeometryType.EPST_Max;
                    return true;
                default:
                    me = EPhysicsShapeGeometryType.EPST_Invalid;
                    return false;
            }
        }

        #endregion
    }

    public struct PhysicsObjectCreationInfo
    {
        #region Data

         // general
        private readonly EPhysicsBaseType _baseType;

        // actor specific
        private EPhysicsSimulation _simType; 

        // shape specific     
        private String _collisionGroupName;

        private String _materialName;

        private Int64   _parentId;

        // shape geometry specific
        private EPhysicsShapeGeometryType _geometryType; 

        private float _dimX;
        private float _dimY;
        private float _dimZ;

        #endregion

        #region Properties
        public EPhysicsSimulation SimType
        {
            get { return _simType; }
            set { _simType = value; }
        }
        public EPhysicsShapeGeometryType GeometryType
        {
            get { return _geometryType; }
            set { _geometryType = value; }
        }
        public System.String CollisionGroupName
        {
            get { return _collisionGroupName; }
            set { _collisionGroupName = value; }
        }
        public System.String MaterialName
        {
            get { return _materialName; }
            set { _materialName = value; }
        }
        public System.Int64 ParentId
        {
            get { return _parentId; }
            set { _parentId = value; }
        }
        public float DimX
        {
            get { return _dimX; }
            set { _dimX = value; }
        }
        public float DimY
        {
            get { return _dimY; }
            set { _dimY = value; }
        }
        public float DimZ
        {
            get { return _dimZ; }
            set { _dimZ = value; }
        }

        #endregion

        #region Ctor

        public PhysicsObjectCreationInfo(EPhysicsBaseType baseType )
        {
            _baseType = baseType;
            _dimX = 3.0f;
            _dimY = 3.0f;
            _dimZ = 3.0f;
            _parentId = -1;
            _simType = EPhysicsSimulation.EPS_Dynamic;
            _geometryType = EPhysicsShapeGeometryType.EPST_Invalid;
            _collisionGroupName = "Static";
            _materialName = "Default";
        }

        #endregion

        #region Methods

        public override string ToString() 
        {
            InteropStructureStringBuilder builder = new InteropStructureStringBuilder();

            builder.BeginStructure();

            builder.AddProperty("type", _baseType.ToFriendlyString());

            // Add simType if actor or shape with no parent
            if( _baseType == EPhysicsBaseType.EPBT_Actor || (( _baseType == EPhysicsBaseType.EPBT_Shape ) && ( ParentId < 0 )) )
            {
                builder.AddSeparator();
                builder.AddProperty("simType", SimType.ToFriendlyString());
            }

            // add shape specific properties
            if (_baseType == EPhysicsBaseType.EPBT_Shape)
            {
                builder.AddSeparator();
                builder.AddProperty("parentId", ParentId.ToString());
                builder.AddSeparator();
                builder.AddProperty("geometryType", GeometryType.ToFriendlyString());
                builder.AddSeparator();
                builder.AddProperty("collisionGroupName", CollisionGroupName, true);
                builder.AddSeparator();
                builder.AddProperty("materialName", MaterialName, true);
                builder.AddSeparator();
                builder.AddProperty("dimX", DimX.ToString());
                builder.AddSeparator();
                builder.AddProperty("dimY", DimY.ToString());
                builder.AddSeparator();
                builder.AddProperty("dimZ", DimZ.ToString());
            }

            builder.EndStructure();

            return builder.Build();
        }

        private void Reset()
        {
            _dimX = 3.0f;
            _dimY = 3.0f;
            _dimZ = 3.0f;
            _parentId = -1;
            _simType = EPhysicsSimulation.EPS_Dynamic;
            _geometryType = EPhysicsShapeGeometryType.EPST_Invalid;
            _collisionGroupName = "Static";
            _materialName = "Default";
        }

        #endregion

    }
}
